Components › Forms & input › Date & time › Date-time range

Date-time range

canon

Start and end with time, all-day toggle and duration presets.

M4c (owner 28 Sep 2026, approved): all-day renders the canonical DateRangeField (from–to in one field, shared calendar, day count) instead of two DateFields with their own day arithmetic — one shape for a range of days; `.dp-field.range` ends share the field width (width 0 + flex 1), so the term row no longer overflows on 390 px (acrm branch feat/celodenni-rozsah). acrm !4087 (28 Sep 2026, owner): the visible duration next to times uses `fmtDurShort` — „45 m“ · „1 h“ · „1 h 30 m“ (in the context of time „m“ = minutes). Screen readers keep the full „min“ via `fmtDur` (TimeField option aria-label, DateTimeRange hidden live text) so „m“ is not read as metres. Other durations in the app (timeline, Setkání, tasks, reminders) keep „min“.

Used in 3 files · 3 areas · 3× — components/calendar, components/meetings, pages/ZasedackyPage

The canonical event term ("Termín" of a meeting or calendar entry). React <DateTimeRangeField> (packages/ui/src/components/DateTimeRangeField.tsx) composes Date field + two Time fields in .dp-stack / .dp-termin / .dp-timegroup, the switches row .dp-switches ("Celý den" and the caller's extras such as "Opakovat") and the availability line .dp-status. Row order follows Google Calendar (AD, ACRM-136, 7 Sep 2026): first the date and the time, then the switches.

When to use

  • Meeting dialog, calendar event, room booking — anything with a start and an end on a clock.
  • All-day events: the toggle hides the times and the day row becomes the canonical Date range field (<DateRangeField>: from–to in one field, one shared calendar, day count) — owner 28 Sep 2026 (acrm M4c): one shape for a range of days in the DS, not two Date fields with their own day arithmetic. A one-day all-day event has from = to.
  • Overnight events (allowOvernight): an end earlier than the start is not an error but "přes půlnoc"; the end day is computed (+1).

When not to use

  • A due date with an optional time (task) — Date field + Time field in the task panel (.dp-addtime / .dp-timerow).
  • A reporting period — Date range.
  • Two dates only, no clock — Date range.

Anatomy

  • .dp-stack: column, gap --sp-3, left-aligned — one gap for every row under the fields, no ad-hoc margins.
  • Row 1 .dp-termin: timed — <DateField futureBias ariaLabel="Datum"> + .dp-timegroup (Time field "Od", .dp-sep, Time field "Do" with getStart, .dp-dur length); all-day — <DateRangeField futureBias presets={[]} fromLabel="Datum" toLabel="Datum konce"> (past-range presets do not fit a future event) + .dp-dur day count when longer than one day. The range field swaps the ends itself. Nothing else sits in this row; the range field may shrink (.dp-termin > .dp-fieldset { min-width: 0 }, full row on phone).
  • Row 2 .dp-switches: the canonical Switch "Celý den" (when allowAllDay, default true) followed by dayExtras from the caller — the meeting dialog puts "Opakovat" and, once on, its frequency · until · end row here. The row is not rendered when there is nothing to put in it.
  • .dp-dur: --small, --fg-secondary; .over note in --warning-ink ("přes půlnoc", "končí 27. 8.").
  • .dp-status.ok (--positive-ink) / .busy (--critical-ink, × icon): text from the availability callback, or the built-in overnight error when allowOvernight is false.
  • Value contract { date, from, to, allDay, toDate } — minutes from midnight, ISO days; the component keeps toDate computed so callers compose startsAt / endsAt only.

Best practices

Do
  • Let the start drag the end: moving "od" keeps the duration (code does this); moving the date moves the whole block.
  • Provide availability for meetings and rooms so the status line answers "is it free" in place.
  • Use allowOvernight for meetings, keep it off for rooms where an end before start is a typo.
Don’t
  • A second date picker asking for the end day of every timed meeting — allowMultiDay was removed for that reason.
  • Duration presets (15 min … 2 h) — removed 6 Sep 2026; the length is written as text after "Do" (.dp-dur).
  • Anything but the date and the time in row 1 — switches and recurrence live in .dp-switches.
  • Status text as a paragraph — one line, state first.
  • A custom toggle for all-day — the canonical control is <Switch> from @acrm/ui in .dp-switches. The old .dp-allday checkbox was removed on 6 Sep 2026 (AD: „předělat na switch“) and the class no longer exists in date-picker.css.

Content

  • Length via fmtDur ("45 min", "1 h 30 min"); days via fmtDays ("2 dny").
  • Overnight note "přes půlnoc"; longer terms "končí 27. 8." (date by formatDate).
  • Built-in error: "Konec je před začátkem — schůzka přes půlnoc není povolená."
  • Toggle label "Celý den"; field labels "Datum", "Datum konce", "Od", "Do" (sentence case).
  • Live region reads "9:00 až 10:30, 1 h 30 min" after every change.
  • date-field, time-field — the parts.
  • date-range — dates only.
  • calendar, picker-panel — the layers the parts open.

Source: docs/date-time/date-time-range.usage.md · GitLab